/*
 * Copyright (c) JiaChaoYang 2023-7-27 MongoPlus版权所有
 * 适度编码益脑，沉迷编码伤身，合理安排时间，享受快乐生活。
 * email: j15030047216@163.com
 * phone: 15030047216
 * weChat: JiaChaoYang_
 */

package com.anwen.mongoa.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.anwen.mongo.conditions.MongoPlusBasicDBObject;
import com.anwen.mongo.conditions.interfaces.condition.CompareCondition;
import com.anwen.mongo.conditions.query.LambdaQueryChainWrapper;
import com.anwen.mongo.constant.IndexConstant;
import com.anwen.mongo.constant.SqlOperationConstant;
import com.anwen.mongo.enums.CompareEnum;
import com.anwen.mongo.enums.LogicTypeEnum;
import com.anwen.mongo.enums.QueryOperatorEnum;
import com.anwen.mongo.enums.SpecialConditionEnum;
import com.anwen.mongo.incrementer.id.IdWorker;
import com.anwen.mongo.manager.MongoPlusClient;
import com.anwen.mongo.mapper.MongoPlusMapMapper;
import com.anwen.mongo.model.PageResult;
import com.anwen.mongo.strategy.convert.ConversionService;
import com.anwen.mongo.strategy.convert.ConversionStrategy;
import com.anwen.mongo.toolkit.CollUtil;
import com.anwen.mongo.toolkit.ObjectIdUtil;
import com.anwen.mongoa.entity.dto.UserDTO;
import com.anwen.mongoa.entity.po.A;
import com.anwen.mongoa.entity.po.B;
import com.anwen.mongoa.entity.po.Role;
import com.anwen.mongoa.entity.po.User;
import com.anwen.mongoa.service.MongoService;
import com.anwen.mongoa.service.RoleService;
import com.anwen.mongoa.service.UserService;
import com.mongodb.BasicDBObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @BelongsProject: mongo-plus-demo
 * @BelongsPackage: com.anwen.mongo.controller
 * @Author: JiaChaoYang
 * @CreateTime: 2023-02-26 17:10
 */
@RequestMapping("/mongo-plus")
@RestController
@Slf4j
@Api(tags = "测试控制类")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private RoleService roleService;

    @Resource
    private MongoPlusMapMapper mongoPlusOperate;

    @Resource
    private MongoTemplate mongoTemplate;

   @Resource
   private MongoPlusClient mongoPlusClient;

    @Resource
    private MongoService mongoService;


    @Resource
    private MongoPlusMapMapper mongoPlusMapMapper;

    @GetMapping("/findAllRole")
    @ApiOperation("查询所有角色")
    public List<Role> findAllRole(@RequestParam(value = "roleName",required = false)String roleName){
        return roleService.lambdaQuery().eq(StringUtils.isNotBlank(roleName), Role::getName, roleName)
                .orderByDesc(Role::getAge).list();
    }


    @PostMapping("/addRole")
    @ApiOperation("添加角色")
    @Transactional
    public Boolean addRole(@RequestBody Role role){
        role.setId(String.valueOf(IdWorker.getId()));
        role.setAge(18);
        // roleService.save(role);
        // Role byId = roleService.getById(role.getId());
        // System.out.println(JSONUtil.toJsonStr(byId));
        // int i = 1/0;
        return roleService.save(role);
    }


    @GetMapping("/userList")
    @ApiOperation("用户列表")
    public PageResult<User> userList() {
        LambdaQueryChainWrapper<User> queryChainWrapper = userService.lambdaQuery();
        return userService.page(queryChainWrapper, 1, 10);
    }

    @GetMapping("/getUserById/{userId}")
    @ApiOperation("查询用户信息")
    public User userList(@PathVariable("userId") Long userId) {
        return userService.getById(userId);
    }


    @GetMapping("/findAllUser")
    @ApiOperation("查询所有用户")
    public Object findAllUser(@RequestParam(value = "userName",required = false)String userName){
        long count = mongoService.count();
        LambdaQueryChainWrapper<User> lambdaQueryChainWrapper = userService.lambdaQuery().like(User::getUserName, "1").like(User::getUserName, "2");
        List<User> userList = userService.lambdaQuery().or(lambdaQueryChainWrapper).list();
        return mongoService.page(1,10);
        /*long action = System.currentTimeMillis();
        log.info("mongoPlus开始时间：{}",action);
        List<Map<String, Object>> mapList = mongoPlusOperate.lambdaQuery().like("userName","英").list("user");
        long end = System.currentTimeMillis();
        log.info("mongoPlus结束时间：{}",end);
        log.error("耗时：{}",end-action);
        return mapList;*/
        /*List<User> userList = userService.lambdaQuery().or(userService.lambdaQuery().eq(User::getUserStatus, 1).eq(User::getUserName,"张三")).list();
        return userList;*/
//        return userService.lambdaQuery().like(StringUtils.isNotBlank(userName), User::getUserName, userName).gt(User::getUserStatus, 2).orderByAsc(User::getCreateTime).list();
    }



    @GetMapping("/findAllUser1111")
    @ApiOperation("查询所有用户")
    public Object findAllUser1111(@RequestParam(value = "userName",required = false)String userName){
//        return userService.lambdaQuery().like(StringUtils.isNotBlank(userName), User::getUserName, userName).orderByAsc(User::getCreateTime).list();
        return userService.lambdaAggregate().skip(1).limit(10).list();
    }

    @GetMapping("/lambdaUpdateUser")
    @ApiOperation("链式调用修改")
//    @MongoTransactional
    public Boolean lambdaUpdateUser(){
        boolean update = userService.lambdaUpdate().eq(User::getUserId,38).set(User::getUserStatus, 0).update();
        log.info("数据更新==>{}",update);
        return update;
        // boolean update = userService.lambdaUpdate().set(User::getUserStatus, 2).eq().update();
        // log.info("{}",update);
        // throw new RuntimeException("asdf");
//        return ;
    }

    @GetMapping("/findAllUserByPage")
    @ApiOperation("分页查询所有用户")
    public PageResult<User> findAllUser(Integer pageNum, Integer pageSize, @RequestParam(value = "userName",required = false) String userName, @RequestParam(value = "roleName",required = false)String roleName){
        Map<Class<?>, ConversionStrategy<?>> allConversion = ConversionService.getAllConversion();
        LambdaQueryChainWrapper<User> queryChainWrapper = userService.lambdaQuery().like(StringUtils.isNotBlank(userName), User::getUserName, userName);
        queryChainWrapper.orderByDesc(User::getCreateTime);
        PageResult<User> page = userService.page(queryChainWrapper, pageNum, pageSize);
        User user = page.getContentData().get(0);
        page.getContentData().forEach(System.out::println);
        return page;
    }



    @PostMapping("/addUser")
    @ApiOperation("添加用户")
//    @Transactional
    public boolean addUser(@RequestBody User user){
//        MongoPlusClient mongoPlusClient1 = mongoPlusClient;
//        System.out.println(mongoPlusClient1);
//        Map<String, MongoClient> mongoClientMap = MongoClientCache.mongoClientMap;
//        mongoClientMap.keySet().forEach(System.out::println);
//        String index = userService.createIndex(Indexes.text(User::getUserName));
//        System.out.println("索引名称："+index);
//        List<Document> documentList = userService.listIndexes();
//        documentList.forEach(System.out::println);
//        MongoCollection<Document> collection = userService.getCollection();
        return userService.save(user);
    }

    @PostMapping("/updateAList")
    @ApiOperation("测试push")
    public boolean updateAList(@RequestBody User user) {
//        userService.lambdaQuery().eq(User::getUserId,1).list();

//        return userService.lambdaUpdate().push(User::getAList, user.getAList()).update();
        return true;
    }

    public static BasicDBObject buildQueryCondition(List<CompareCondition> compareConditionList) {
        MongoPlusBasicDBObject mongoPlusBasicDBObject = new MongoPlusBasicDBObject();
        if (CollUtil.isNotEmpty(compareConditionList)) {
            List<CompareCondition> conditionList = compareConditionList.stream().filter(compareCondition -> compareCondition.getType() == CompareEnum.QUERY.getKey()).collect(Collectors.toList());
            conditionList.forEach(compare -> {
                if (Objects.equals(compare.getCondition(), QueryOperatorEnum.LIKE.getValue()) && com.anwen.mongo.toolkit.StringUtils.isNotBlank(String.valueOf(compare.getValue()))) {
                    mongoPlusBasicDBObject.put(compare.getColumn(), new BasicDBObject(SpecialConditionEnum.REGEX.getCondition(), compare.getValue()));
                } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.OR.getKey())) {
                    if (null == compare.getChildCondition() || compare.getChildCondition().isEmpty()) {
                        compare.setChildCondition(Collections.singletonList(compare));
                    }
                    mongoPlusBasicDBObject.put(SpecialConditionEnum.OR.getCondition(), buildOrQueryCondition(compare.getChildCondition()));
                } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.NOR.getKey())) {
                    mongoPlusBasicDBObject.put(SpecialConditionEnum.NOR.getCondition(), buildQueryCondition(compare.getChildCondition()));
                } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.ELEMMATCH.getKey())) {
                    mongoPlusBasicDBObject.put(compare.getColumn(),new BasicDBObject(SpecialConditionEnum.ELEM_MATCH.getCondition(),buildQueryCondition(compare.getChildCondition())));
                } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.TEXT.getValue())) {
                    mongoPlusBasicDBObject.put(SpecialConditionEnum.TEXT.getCondition(), new BasicDBObject(SpecialConditionEnum.SEARCH.getCondition(), compare.getValue()));
                    IndexConstant.createIndex = compare.getColumn();
                } else if (Objects.equals(compare.getColumn(), SqlOperationConstant._ID)) {
                    if (SpecialConditionEnum.IN.getCondition().equals("$" + compare.getCondition())) {
                        mongoPlusBasicDBObject.put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), ObjectIdUtil.convertObjectId((Collection<?>)compare.getValue())));
                    } else {
                        mongoPlusBasicDBObject.put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), ObjectIdUtil.convertObjectId(compare.getValue())));
                    }
                } else {
                    mongoPlusBasicDBObject.put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), compare.getValue()));
                }
            });
        }
        return mongoPlusBasicDBObject;
    }

    /**
     * 构建子条件
     *
     * @author JiaChaoYang
     * @date 2023/7/16 19:59
     */
    public static List<BasicDBObject> buildOrQueryCondition(List<CompareCondition> compareConditionList) {
        return new ArrayList<BasicDBObject>(){{
            compareConditionList.forEach(compare -> {
                add(new MongoPlusBasicDBObject(){{
                    if (Objects.equals(compare.getCondition(), QueryOperatorEnum.LIKE.getValue()) && com.anwen.mongo.toolkit.StringUtils.isNotBlank(String.valueOf(compare.getValue()))) {
                        put(compare.getColumn(), new BasicDBObject(SpecialConditionEnum.REGEX.getCondition(), compare.getValue()));
                    } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.AND.getValue())) {
                        add(buildQueryCondition(compare.getChildCondition()));
                    } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.TEXT.getValue())) {
                        put(SpecialConditionEnum.TEXT.getCondition(), new BasicDBObject(SpecialConditionEnum.SEARCH.getCondition(), compare.getValue()));
                        IndexConstant.createIndex = compare.getColumn();
                    } else if (Objects.equals(compare.getColumn(), SqlOperationConstant._ID)){
                        //如果是objectId
                        if (ObjectId.isValid(String.valueOf(compare.getValue()))){
                            put(compare.getColumn(),new BasicDBObject("$"+compare.getCondition(),new ObjectId(String.valueOf(compare.getValue()))));
                        } else {
                            put(compare.getColumn(),new BasicDBObject("$"+compare.getCondition(),String.valueOf(compare.getValue())));
                        }
                    } else {
                        put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), compare.getValue()));
                    }
                }});
            });
        }};
    }

    /**
     * 实体转map
     * @author JiaChaoYang
     * @date 2023/11/6 16:26
     */
    private Map<String,Object> entityConversionMap(Object param){
        return entityConversionMap(param,String.class,Object.class);
    }

    private <K,V> Map<K,V> entityConversionMap(Object param,Class<K> keyClazz,Class<V> valueClazz){
        return JSON.parseObject(JSON.toJSONString(param),new TypeReference<Map<K,V>>(keyClazz,valueClazz){});
    }

    @Resource
    private MongoPlusMapMapper mapper;

    @PostMapping("/addA")
    @ApiOperation("添加用户")
    public void addUser(@RequestBody A a){
        A a1 = new A();
        B b = new B();
        b.setId(1L);
        a1.setId(2L);
        mongoTemplate.save(a1);
        List<A> all = mongoTemplate.findAll(A.class, "a");
        System.out.println(all);
    }

    @PostMapping("/addBatchUser")
    @ApiOperation("批量添加用户")
    public Object addBatchUser(@RequestBody UserDTO userDTO){
        return userService.saveBatch(userDTO.getUserList());
    }

    @PostMapping("/updateUserById")
    @ApiOperation("根据id修改用户")
    public Object updateUserById(@RequestBody User user){
        return userService.updateById(user);
    }

    @PostMapping("/updateBatchUserByIds")
    @ApiOperation("批量根据id修改用户")
    public Object updateBatchUserByIds(@RequestBody UserDTO userDTO){
        return userService.updateBatchByIds(userDTO.getUserList());
    }

    @PostMapping("/saveOrUpdateUser")
    @ApiOperation("添加或修改用户")
    public Object saveOrUpdateUser(@RequestBody User user){
        return userService.saveOrUpdate(user);
    }

    @PostMapping("/saveOrUpdateBatchUser")
    @ApiOperation("添加或修改多个用户")
    public Object saveOrUpdateBatchUser(@RequestBody UserDTO userDTO){
        return userService.saveOrUpdateBatch(userDTO.getUserList());
    }

    @DeleteMapping("/deleteById/{id}")
    @ApiOperation("根据id删除用户")
    public Boolean deleteUserById(@PathVariable("id") Long userId){
        return userService.lambdaUpdate().eq(User::getUserId, userId).remove();
    }

//    @Override
//    public void convertValue(Field field, Object obj, Object fieldValue) throws IllegalAccessException {
//
//    }

/*    @PostMapping("/deleteUserByIds")
    @ApiOperation("根据ids删除用户")
    public Object deleteUserByIds(@RequestBody List<String> ids){
        return userService.removeBatchByIds(ids);
    }*/

}
